home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Games / flying-6.11 / carrom.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-30  |  11.4 KB  |  426 lines

  1. #ifndef _global_h
  2. #    include "global.h"
  3. #endif
  4.  
  5. #ifndef _carrom_h
  6. #    include "carrom.h"
  7. #endif
  8. #ifndef _wall_h
  9. #    include "wall.h"
  10. #endif
  11. #ifndef _graph_h
  12. #    include "graph.h"
  13. #endif
  14. #ifndef _mover_h
  15. #    include "mover.h"
  16. #endif
  17. #ifndef _arcs_h
  18. #    include "arcs.h"
  19. #endif
  20. #ifndef _pocket_h
  21. #    include "pocket.h"
  22. #endif
  23.  
  24.  
  25.  
  26. void Carrom::InitArea( double wx, double wy ) {
  27.     area_width    = wx;
  28.     area_height    = wy;
  29.     area_off_x = (MaxX()-ToPocket-PocketWidth-area_width)/2.0;
  30.     area_off_y = (MaxY()-area_height)/2.0;
  31. }
  32.  
  33.  
  34. Carrom::Carrom(double wx, double wy) :
  35.     Game(wx+2.0*FrameOffset+PocketWidth+ToPocket,wy+2.0*FrameOffset)
  36. {
  37.     InitArea(wx,wy);
  38.  
  39.     table_col    = SetMainBgColor( "Tan" );        // GlobalBackground
  40.  
  41.     table_black    = AddBgColor( "black" );
  42.     table_red    = AddBgColor( "Brown" );
  43.     table_green = AddBgColor( "DarkGreen" );
  44.     pocket_col    = CreateColorMix( table_col, table_green );
  45.  
  46. #ifndef __TURBOC__
  47.     white_col    = AddBallColor( "DarkGoldenrod" );
  48.     black_col    = AddBallColor( "black" );
  49.     queen_col    = AddBallColor( "red" );
  50.     striker_col    = AddBallColor( "DeepSkyBlue" );
  51. #else
  52.     white_col    = AddBallColor( "DarkGoldenrod" );
  53.     floor            = CreateColorMix( table_green, table_black );
  54.  
  55.     black_col    = AddBallColor( "black" );
  56.     queen_col    = AddBallColor( "red" );
  57.     striker_col    = CreateColorMix( white_col, black_col );
  58. #endif
  59.  
  60.     AddShadeColor( "grey", 1, 2 );
  61.     SetCursorColor( "White" );
  62.     striker = 0;
  63.     striker_in_pocket = 0;
  64.     queen_in_pocket   = 0;
  65.     whites_in_pocket  = 0;
  66.     blacks_in_pocket  = 0;
  67.  
  68.     keeper = new StackKeeper(PocketWidth,PocketFrame,table_black);
  69. }
  70.  
  71. Carrom::~Carrom() {
  72.     if (striker) {
  73.         delete queen;
  74.         delete striker;
  75.         for (int i=0;i<9;i++) {
  76.             delete white[i];
  77.             delete black[i];
  78.         }
  79.         striker=0;
  80.     }
  81.  
  82.     for (int i=0;i<4;i++) {
  83.         if (e[i][0])        delete e[i][0];
  84.         if (e[i][1])        delete e[i][1];
  85.         if (p[i])            delete p[i];
  86.         if (w[i])            delete w[i];
  87.     }
  88.  
  89.     if (mstone)        delete mstone;
  90.     if (mstriker)    delete mstriker;
  91. }
  92.  
  93. const Real & Carrom::GetPresetA() const            { return PresetA; }
  94. const Real & Carrom::GetPresetHaft() const        { return PresetHaft; }
  95. const Real & Carrom::GetSlowGranularity() const    { return SlowGranularity; }
  96.  
  97. const Real & Carrom::GetNormalBallSize() const    { return StoneRadius; }
  98.  
  99. const Real & Carrom::GetChargeGranularity() const    { return ChargeGranularity; }
  100. const Real & Carrom::GetChargeSpeed() const            { return ChargeSpeed; }
  101. const Real & Carrom::GetMaxCharge() const            { return MaxCharge; }
  102. const Real & Carrom::GetShootTime() const            { return ShootTime; }
  103.  
  104. const Real Carrom::AreaOffX() const            { return area_off_x; }
  105. const Real Carrom::AreaOffY() const            { return area_off_y; }
  106. const Real Carrom::AreaWidth() const        { return area_width; }
  107. const Real Carrom::AreaHeight() const        { return area_height; }
  108.  
  109. const Real Carrom::TAreaOffX() const        { return area_off_x-Cushion; }
  110. const Real Carrom::TAreaOffY() const        { return area_off_y-Cushion; }
  111. const Real Carrom::TAreaWidth() const        { return area_width+2.0*Cushion; }
  112. const Real Carrom::TAreaHeight() const        { return area_height+2.0*Cushion; }
  113.  
  114. void Carrom::Setup( double x, double y )
  115. {
  116. static int    nc[5] = { 3, 4, 5, 4, 3 };        // Steine pro Spalte
  117. static t[19] = { -1,  1, -2,                    // Steinverteilung
  118.                      2, -3,  3,  4,
  119.                  -4,  5,  0, -5, -6,
  120.                      6, -7,  7,  8,
  121.                       -8,  9, -9 };
  122.  
  123. const int count = 5;
  124. int        c=0;
  125. double    cdist = sqrt( 3.*(GetNormalBallSize()+Offset)*(GetNormalBallSize()+Offset) );
  126. Ball    *r;
  127.  
  128.     x-=(cdist*(count-1)/2.0);
  129.     for( int col=0; col<count; col++ ) {
  130.         for( int row=0; row<nc[col]; row++ ) {
  131.             r=new Ball( x+col*cdist, y+(row-nc[col]/2.0+0.5)*2.0*(GetNormalBallSize()+Offset), 0, 0, GetNormalBallSize(), StoneWeight );
  132.             if (t[c]>0) {
  133.                 r->state = new BallState( mstone, white_col, r->P() );
  134.                 white[t[c]-1] = r;
  135.             }
  136.             else if (t[c]<0) {
  137.                 r->state = new BallState( mstone, black_col, r->P() );
  138.                 black[-t[c]-1] = r;
  139.             }
  140.             else {
  141.                 r->state = new BallState( mstone, queen_col, r->P() );
  142.                 queen = r;
  143.             }
  144.             c++;
  145.         }
  146.     }
  147. }
  148.  
  149.  
  150.  
  151.  
  152. void Carrom::InitPlayground() {
  153. int i;
  154.  
  155.     mstone = new DiscMover( GetNormalBallSize() );
  156.     mstone->Init();
  157.     DBG2(UnixTrace, "Carrom: Stone-Radius set back from %g to %g\n",
  158.                     (double)StoneRadius, (double)mstone->GetActRadius() );
  159.     StoneRadius = mstone->GetActRadius();
  160.  
  161.     mstriker = new BallMover( StrikerRadius );
  162.     mstriker->Init();
  163.     DBG2(UnixTrace, "Carrom: Striker-Radius set back from %g to %g\n",
  164.                     (double)StrikerRadius, (double)mstriker->GetActRadius() );
  165.     StrikerRadius = mstriker->GetActRadius();
  166.  
  167.     Game::InitPlayground();
  168. #if (0)
  169. #ifdef DEBUG
  170.     if (debug&ShowLight) {
  171.         mstone->CreateLightWindow();
  172.     }
  173. #endif
  174. #endif
  175.  
  176.     p[0] = new Pocket( AreaOffX(), AreaOffY(), PocketRadius );
  177.     p[1] = new Pocket( AreaOffX()+AreaWidth(), AreaOffY(), PocketRadius );
  178.     p[2] = new Pocket( AreaOffX()+AreaWidth(), AreaOffY()+AreaHeight(), PocketRadius );
  179.     p[3] = new Pocket( AreaOffX(), AreaOffY()+AreaHeight(),    PocketRadius );
  180.  
  181.     for (i=0;i<4;i++) {
  182.         e[i][0] = new StaticBall( p[i]->P()+PocketRadius*Vec2(1.0,RealZero).TurnAngleDeg(-90.*i),    0.0 );
  183.         e[i][1] = new StaticBall( p[i]->P()+PocketRadius*Vec2(1.0,RealZero).TurnAngleDeg(-90.*i-90.),0.0 );
  184.     }
  185.     for (i=0;i<4;i++) {
  186.         w[i] = new Wall( e[i][0]->P(), e[(i+1)%4][1]->P() );
  187.     }
  188.  
  189.     mid = Vec2( AreaOffX()+AreaWidth()/2.0, AreaOffY()+AreaHeight()/2.0 );
  190.     Vec2 d(1.0,0.0);
  191.     for (i=0;i<4;i++) {
  192.         base[i][0] = mid+25.*d.TurnAngleDeg(-90.*i)+22.*d.TurnAngleDeg(90.*(i+1));
  193.         base[i][1] = mid+25.*d.TurnAngleDeg(-90.*i)+22.*d.TurnAngleDeg(90.*(i-1));
  194.     }
  195.     Setup(AreaOffX()+AreaWidth()/2.0, AreaOffY()+AreaHeight()/2.0);
  196.  
  197.     striker = new Ball( (base[1][0]+base[1][1])/2.0, StrikerRadius, StrikerWeight );
  198.     striker->state = new BallState( mstriker, striker_col, striker->P() );
  199. }
  200.  
  201.  
  202.  
  203.  
  204. void Carrom::DrawBackground() const {
  205. int i;
  206. int j;
  207.  
  208. const Real    w8  =  45.0;
  209. const Real    w16 =  w8/2.0;
  210. const Real    w32 = w16/2.;
  211. const Real    w64 = w32/2.;
  212.  
  213. Vec2    d(1.0,0.0);
  214. Vec2    p1,p2,p3,p4;
  215.  
  216.     Game::DrawBackground();
  217.  
  218. // normales Spielfeld
  219.     SetBgColor( table_black );
  220.     FillRectangle( TAreaOffX(), TAreaOffY(), TAreaWidth(), TAreaHeight() );
  221.     SetBgColor(0);
  222.     FillRectangle( AreaOffX(), AreaOffY(), AreaWidth(), AreaHeight() );
  223.  
  224. //
  225. // Randelemente und Taschen aufbauen (4er-Schleife)
  226. //
  227.     for (i=0;i<4;i++) {
  228.         SetBgColor(pocket_col);
  229.         FillCircle( p[i]->P(), p[i]->R() );
  230.     Real    ang = w8*Real(2*i+1);
  231.         SetBgColor(table_black);
  232.         DrawLine( mid+16.0*d.TurnAngleDeg(ang), mid+42.0*d.TurnAngleDeg(ang) );
  233.         DrawArc(  mid+19.5*d.TurnAngleDeg(ang), 3.5, ang+30.0, 300. );
  234.  
  235.         SetBgColor( table_black );
  236.         p1 = base[i][0] + 1.8*d.TurnAngleDeg(90.*i);
  237.         p2 = base[i][0] + 1.3*d.TurnAngleDeg(90.*i);
  238.         p3 = base[i][1] + 1.3*d.TurnAngleDeg(90.*i);
  239.         p4 = base[i][1] + 1.8*d.TurnAngleDeg(90.*i);
  240.         FillPoly( 4, &p1, &p2, &p3, &p4 );
  241.         p1 = base[i][0] - 1.8*d.TurnAngleDeg(90.*i);
  242.         p2 = base[i][0] - 1.6*d.TurnAngleDeg(90.*i);
  243.         p3 = base[i][1] - 1.6*d.TurnAngleDeg(90.*i);
  244.         p4 = base[i][1] - 1.8*d.TurnAngleDeg(90.*i);
  245.         FillPoly( 4, &p1, &p2, &p3, &p4 );
  246.  
  247.         for (j=0;j<2;j++) {
  248.             SetBgColor( table_black );            FillCircle( base[i][j], 3.6/2 );
  249.             SetBgColor( table_col );            FillCircle( base[i][j], 3.3/2 );
  250.             SetBgColor( table_red );            FillCircle( base[i][j], 3.5/2 );
  251.         }
  252.     }
  253.  
  254. //
  255. // Kreise in der Mitte ziehen
  256. //
  257.     SetBgColor( table_black );      FillCircle( mid, 21.5 / 2 );
  258.     SetBgColor( table_red );          FillCircle( mid, 21.2 / 2 );
  259.     SetBgColor( table_black );      FillCircle( mid, 20.8 / 2 );
  260.     SetBgColor( table_col );          FillCircle( mid, 20.5 / 2 );
  261.  
  262.     SetBgColor( table_black );      FillCircle( mid, 16.1 / 2 );
  263.     SetBgColor( table_col );          FillCircle( mid, 15.9 / 2 );
  264.  
  265.     SetBgColor( table_black );      FillCircle( mid, 15.6 / 2 );
  266.     SetBgColor( table_red );          FillCircle( mid, 15.5 / 2 );
  267.     SetBgColor( table_black );      FillCircle( mid, 15.1 / 2 );
  268.     SetBgColor( table_col );          FillCircle( mid, 15.0 / 2 );
  269.  
  270.     SetBgColor( table_black );      FillCircle( mid, 14.60 / 2 );
  271.     SetBgColor( table_col );          FillCircle( mid, 14.35 / 2 );
  272.  
  273. //
  274. // mittleren Kreis in 8 Segmenten aufbauen
  275. //
  276.     for (i=0;i<8;i++) {
  277.         d = Vec2(1.0,RealZero).TurnAngleDeg( w8 * (double)i );
  278.  
  279.         SetBgColor(table_black);
  280.         for (double j=0.;j<4.;j++) {
  281.             p1 = mid+8.0*d.TurnAngleDeg(j*w32);
  282.             p2 = mid+8.7*d.TurnAngleDeg(j*w32+5.0);
  283.             p3 = mid+8.7*d.TurnAngleDeg(j*w32-5.0);
  284.             FillPoly(3, &p1, &p2, &p3 );
  285.             Real    ang=w8*Real(i)+w32*j+w64;
  286.             DrawArc(mid+9.*Vec2(1.0,RealZero).TurnAngleDeg(ang),0.95,ang-90.,180.);
  287.         }
  288.  
  289.         SetBgColor(table_red);
  290.         FillCircle( mid+3.0*d.TurnAngleDeg(w16), 0.7 );
  291.         for (j=1;j<8;j+=4)    FillCircle(mid+9.0*d.TurnAngleDeg(w64*j),0.6);
  292.         SetBgColor(table_green);
  293.         for (j=3;j<8;j+=4)    FillCircle(mid+9.0*d.TurnAngleDeg(w64*j),0.6);
  294.  
  295.             p1=mid+3.0*d;
  296.             p2=mid+4.0*d.TurnAngleDeg( 10.0);
  297.             p3=mid+8.5*d;
  298.             p4=mid+4.0*d.TurnAngleDeg(-10.0);
  299.         FillPoly( 4, &p1, &p2, &p3, &p4 );
  300.             p2 = mid+1.5*d.TurnAngleDeg( 5.0*w16);
  301.             p3 = mid+1.5*d.TurnAngleDeg(-5.0*w16);
  302.         FillPoly( 3, &p1, &p2, &p3 );
  303.  
  304.         Vec2    s[10];        // Stern
  305.             s[0] = mid+4.7*d.TurnAngleDeg(w16);
  306.             s[1] = mid+4.3*d.TurnAngleDeg(w16+12.);
  307.             s[2] = mid+5.2*d.TurnAngleDeg(w16+9.);
  308.             s[3] = mid+6.2*d.TurnAngleDeg(w16+13.);
  309.             s[4] = mid+6.2*d.TurnAngleDeg(w16+5.);
  310.  
  311.             s[5] = mid+7.2*d.TurnAngleDeg(w16);
  312.             s[6] = mid+6.2*d.TurnAngleDeg(w16-5.);
  313.             s[7] = mid+6.2*d.TurnAngleDeg(w16-13.);
  314.             s[8] = mid+5.2*d.TurnAngleDeg(w16-9.);
  315.             s[9] = mid+4.3*d.TurnAngleDeg(w16-12.);
  316.         FillPoly( 10, s );
  317.     }
  318.  
  319.     SetBgColor(table_red);
  320.     FillCircle(mid,1.2);
  321. }
  322.  
  323. //////////////////////////////////////////////////////////////////////////////
  324.  
  325. void Carrom::InPocket( Ball *b ) {
  326.     Game::InPocket(b);
  327.     if (b==striker)        {    striker_in_pocket = 1;    return;    }
  328.     if (b==queen)            {    queen_in_pocket   = 1;    return;    }
  329.     for (int i=0;i<9;i++) {
  330.         if (b==white[i])    {    whites_in_pocket |= (1<<i);    return;    }
  331.         if (b==black[i])    {    blacks_in_pocket |= (1<<i);    return;    }
  332.     }
  333. }
  334.  
  335. void Carrom::AllBallsStopped() {
  336.     Game::AllBallsStopped();
  337.     (void)IsSelectable(striker);        // back on the table
  338. }
  339.  
  340. void Carrom::ResetToCenter(Ball *b) {
  341. Vec2    center(AreaOffX()+AreaWidth()/2.0, AreaOffY()+AreaHeight()/2.0);
  342.  
  343.     Vec2    newpos;
  344.     b->FitsNextTo(center,Vec2(1.0,RealZero),&newpos);
  345.     b->SetP(newpos);                    // closer to right wall
  346.  
  347.     b->ChgV(Vec2Zero);
  348. }
  349.  
  350. int Carrom::IsSelectable(Ball *b) {
  351.     if (b==striker) {
  352.         if (striker_in_pocket) {
  353.             Vec2    inspos(AreaOffX()+AreaWidth()-2.0*StrikerRadius-EPS,
  354.                                                         AreaOffY()+AreaHeight()/2.0);
  355.             Vec2    newpos;
  356.  
  357.             b->FitsNextTo(inspos,Vec2(-1.0,RealZero),&newpos);
  358.             striker_in_pocket = 0;
  359.             b->SetP(newpos);
  360.             b->ChgV(Vec2Zero);
  361.  
  362.             return 0;
  363.         }
  364.         else {
  365.             return 1;
  366.         }
  367.     }
  368.     for (int i=0;i<9;i++) {
  369.         if ( b==white[i] ) {
  370.             if (whites_in_pocket&(1<<i)) {
  371.                     ResetToCenter(b);
  372.                     whites_in_pocket &= ~(1<<i);
  373.                     return 0;
  374.             }
  375.             else    return 1;
  376.         }
  377.         if ( b==black[i] ) {
  378.             if (blacks_in_pocket&(1<<i)) {
  379.                     ResetToCenter(b);
  380.                     blacks_in_pocket &= ~(1<<i);
  381.                     return 0;
  382.             }
  383.             else    return 1;
  384.         }
  385.     }
  386.     if ( b==queen ) {
  387.         if (queen_in_pocket) {
  388.                 ResetToCenter(b);
  389.                 queen_in_pocket = 0;
  390.                 return 0;
  391.         }
  392.         else    return 1;
  393.     }
  394.  
  395.     return Game::IsSelectable(b);
  396. }
  397.  
  398. // -------------------------------------------------------------------------
  399.  
  400. CarromDemo::~CarromDemo() {}
  401.  
  402. const Real &CarromDemo::GetPresetA() const            { return PresetA; }
  403. const Real &CarromDemo::GetSlowGranularity() const    { return SlowGranularity; }
  404.  
  405. void CarromDemo::InitPlayground() {
  406.     Carrom::InitPlayground();
  407.     for (int i=0;i<4;i++) {
  408.         delete e[i][0];    e[i][0]=0l;
  409.         delete e[i][1];    e[i][1]=0l;
  410.         Vec2    pos( p[i]->P() );
  411.         delete p[i];
  412.         p[i] = new StaticBall( pos, PocketRadius );
  413.     }
  414.  
  415.     striker->v = Vec2(1.0,-shot_speed);
  416. }
  417.  
  418. void CarromDemo::DrawBackground() const {
  419.     Carrom::DrawBackground();
  420.     SetBgColor(table_black);
  421.     for (int i=0;i<4;i++) {
  422.         FillCircle( p[i]->P(), p[i]->R() );
  423.     }
  424. }
  425.  
  426.